package com.wwu.common.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import eu.bitwalker.useragentutils.Version;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;

/**
 * SpringContext工具类
 * @author 一蓑烟雨
 * @version 1.0.0
 * @date 2023-05-31 21:17
 */
@Component
public class SpringUtils implements ApplicationContextAware {
    /** 地址常量 */
    public  static  final  String  IP_UNKNOWN = "unknown";

    /** 上下文对象实例 */
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    /**
     * 获取applicationContext上下文
     * @return org.springframework.context.ApplicationContext
     * @author 一蓑烟雨
     * @date 2023/5/31 21:35
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 获取HttpServletRequest
     * @return javax.servlet.http.HttpServletRequest
     * @author 一蓑烟雨
     * @date 2023/5/31 21:36
     */
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    /**
     * 获取HttpServletResponse
     * @return javax.servlet.http.HttpServletResponse
     * @author 一蓑烟雨
     * @date 2023/5/31 21:36
     */
    public static HttpServletResponse getHttpServletResponse() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    }

    /**
     * 获取HttpHttpSession
     * @param request
     * @return javax.servlet.http.HttpSession
     * @author 一蓑烟雨
     * @date 2023/7/28 7:55
     */
    public static HttpSession getHttpSession(HttpServletRequest request) {
        return request.getSession();
    }

    /**
     * 获取请求的url地址
     * @param request
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:42
     */
    public static String getRequestURI(HttpServletRequest request) {
        return request.getRequestURI();
    }

    /**
     * 获取请求的方式
     * @param request
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/7/28 8:16
     */
    public static String getRequestMethod(HttpServletRequest request) {
        return request.getMethod();
    }

    /**
     * 获取主机名
     * @param request
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/7/28 8:09
     */
    public static String getRemoteHost(HttpServletRequest request) {
        try {
            return  request.getRemoteHost().equals("0:0:0:0:0:0:0:1") ? "localhost" : request.getRemoteHost();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "主机名获取失败";
    }

    /**
     * 获取请求的主机名和端口
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:42
     */
    public static String getOrigin(HttpServletRequest request) {
        return request.getHeader("Origin");
    }

    /**
     * 获取客户端真实ip地址
     * @param request
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/7/28 8:15
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = null;
        try {
            ip = request.getHeader("x-forwarded-for");
            if (!StringUtils.hasText(ip) || IP_UNKNOWN.equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (!StringUtils.hasText(ip) || ip.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (!StringUtils.hasText(ip) || IP_UNKNOWN.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (!StringUtils.hasText(ip) || IP_UNKNOWN.equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (!StringUtils.hasText(ip) || IP_UNKNOWN.equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return ip.equals("0:0:0:0:0:0:0:1")  ? "127.0.0.1" :ip;
    }

    /**
     * 获取浏览器和操作系统信息
     * @param request
     * @return java.util.HashMap<java.lang.String,java.lang.String>
     * @author 一蓑烟雨
     * @date 2023/7/29 11:04
     */
    public static HashMap<String,String> getBrowserAndOsInfo(HttpServletRequest request) {
        HashMap<String, String> hashMap = new HashMap<>();
        String agentStr = request.getHeader("user-agent");
        UserAgent agent = UserAgent.parseUserAgentString(agentStr);

        //浏览器信息
        Browser browser = agent.getBrowser();
        //获取浏览器类型
        hashMap.put("browserType",browser.getBrowserType().toString());
        //获取浏览器产品系列
        hashMap.put("browserGroup",browser.getGroup().toString());
        //获取浏览器名称
        hashMap.put("browserName",browser.getName().toString());
        //获取浏览器厂商
        hashMap.put("browserManufacturer",browser.getManufacturer().toString());
        //获取浏览器引擎
        hashMap.put("browserEngine",browser.getRenderingEngine().toString());

        //浏览器版本信息
        Version version = agent.getBrowserVersion();
        //获取浏览器主版本
        hashMap.put("browserMajorVersion",version.getMajorVersion());
        //获取浏览器小版本
        hashMap.put("browserMinorVersion",version.getMinorVersion());
        //获取浏览器完整版本
        hashMap.put("browserVersion",version.getVersion());

        //操作系统信息
        OperatingSystem system = agent.getOperatingSystem();
        //获取操作系统名称
        hashMap.put("osName",system.getName().toString());
        //获取操作系统设备类型
        hashMap.put("osType",system.getDeviceType().toString());
        //获取操作系统系列
        hashMap.put("osGroup",system.getGroup().toString());
        //获取操作系统厂商
        hashMap.put("osManufacturer",system.getManufacturer().toString());

        return hashMap;
    }

    /**
     * 获取请求中的指定参数
     * @param request
     * @param paramName
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/8/1 18:20
     */
    public static String getRequestBodyParam(HttpServletRequest request,String paramName) {
        HashMap<String,Object> hashMap = getRequestBodyParams(request);
        if(hashMap.containsKey(paramName) && !ObjectUtils.isEmpty(hashMap.get(paramName))){
             return hashMap.get(paramName).toString();
        }
        return null;
    }

    /**
     * 获取请求中的所有参数
     * @param request
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/7/28 8:16
     */
    public static HashMap<String,Object> getRequestBodyParams(HttpServletRequest request) {
        HashMap<String,Object> hashMap = new HashMap<>();
        hashMap = (HashMap<String, Object>) request.getAttribute("PARSED_BODY");
        try {
            if(ObjectUtils.isEmpty(hashMap)){
                ServletInputStream inputStream = request.getInputStream();
                StringBuilder content = new StringBuilder();
                byte[] b = new byte[1024];
                int lens;
                while ((lens = inputStream.read(b)) > 0) {
                    content.append(new String(b, 0, lens));
                }
                ObjectMapper mapper = new ObjectMapper();
                hashMap = mapper.readValue(content.toString(), HashMap.class);

                request.setAttribute("PARSED_BODY",hashMap);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

        return hashMap;
    }

    /**
     * 获取指定名称的Bean对象
     * @param name
     * @return java.lang.Object
     * @author 一蓑烟雨
     * @date 2023/5/31 21:38
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 根据类获取Bean对象
     * @author 一蓑烟雨
     * @date 2023/5/31 21:37
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 根据类获取指定名称的Bean对象
     * @param name
     * @param clazz
     * @return T
     * @author 一蓑烟雨
     * @date 2023/5/31 21:36
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}
